package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.PasswordConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.EmployeeDTO;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.entity.Employee;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.result.PageResult;
import com.sky.service.EmployeeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
//        下面这里写一个todo可以方便表示有什么地方没有完善完整，到时候直接修改
        // TODO 后期需要进行md5加密，然后再进行比对

//        下面就是对代码进行md5加密
//        其实本质就是数据库的存放密码的那一部分先存放的是
//        加密之后的字符串，然后只需要把前端的密码加密之后得到的
//        字符串和后端数据库的秘密密文进行比对就可以了然后md5
//        加密是单向的，不能从密文转变成原文本。这个数据库加密主要是为了防止
//        数据库泄露直接把密码暴露出来了。所以这里加密的代码除了
//        需要写下面这个加密之外，还需要在数据库那里修改数据信息
        password=DigestUtils.md5DigestAsHex(password.getBytes());

//        e10adc3949ba59abbe56e057f20f883e
//        上面这个是md5加密之后的密文，对应的数据是123456

        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }

    @Override
    public void save(EmployeeDTO employeeDTO) {

        System.out.println("当前线程的id:"+Thread.currentThread().getId());

        Employee employee=new Employee();

        BeanUtils.copyProperties(employeeDTO,employee);

        employee.setStatus(StatusConstant.ENABLE);

        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
//
//        既然已经使用了Autofill注解作为切面了，那就不需要在这里的save和下面的update进行的set设置了
//        employee.setCreateTime(LocalDateTime.now());
//        employee.setUpdateTime(LocalDateTime.now());


//        //TODO 后期需要修改为当前登录用户的id
//        employee.setCreateUser(BaseContext.getCurrentId());
//        employee.setUpdateUser(BaseContext.getCurrentId());

        employeeMapper.insert(employee);

    }

//    这个是实现接口的方法
    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {

//        这里使用的是pagehelper的这一个依赖工具，用于方便实现页面查询
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());

//        然后这里算是创建一个变量来承接employeemapper的方法返回的数据
//        然后这里的pageQuery只是和这个方法名称重名了而已，其实本质上是
//        调用的employeemapper里面使用的mybatis的方法。
        Page<Employee> page=employeeMapper.pageQuery(employeePageQueryDTO);

//        然后下面就是返回页数总数保留这个数据
        long total =page.getTotal();

//        创建列表承接employee
        List<Employee> records =page.getResult();

//        然后把总页数和承载员工信息的列表返
        return new PageResult(total,records);
    }


    /***
     * 启用禁用员工账号
     *
     * @param status
     * @param id
     */
    public void startOrStop(Integer status,Long id){

//        有两种写的方法，然后就是用不用builder的区别
//        Employee employee =new Employee();
//        employee.setStatus(status);
//        employee.setId(id);

        Employee employee=Employee.builder()
                .status(status)
                .id(id)
                .build();

        employeeMapper.update(employee);

    }

    @Override
    public Employee getById(Long id) {

//        然后写到这一步的时候卡壳了，看了一眼黑马。他是这么写的：
//        首先是直接调用mapper持久层，然后把方法调用都写好了之后再声明承载的对象

        Employee employee= employeeMapper.getById(id);

//        传给前端的密码就是设置为不可见
        employee.setPassword("******");
        return employee;
    }

    @Override
    public void update(EmployeeDTO employeeDTO) {
        Employee employee=new Employee();

        BeanUtils.copyProperties(employeeDTO,employee);

//        employee.setUpdateTime(LocalDateTime.now());
//
//        employee.setUpdateUser(BaseContext.getCurrentId());

        employeeMapper.update(employee);

    }
}
